---
title: Plan and manually apply Terraform resources
hide_title: true
---

# Use TF-controller to plan and manually apply Terraform resources

TF-controller is a tool that allows you to manage infrastructure as code
using Terraform within a Kubernetes cluster. With TF-controller, you can
define your infrastructure in a declarative way and have it automatically managed and updated.

In this guide, we will walk through the steps of using TF-controller to plan and
manually apply Terraform resources.
This involves creating a `Terraform` object and a `GitRepository` object,
and then using kubectl to view the plan before applying it.

We will start by creating the `Terraform` object and specifying the necessary fields,
including the `approvePlan` field.
We will then create the `GitRepository` object,
which points to the Git repository containing the Terraform configuration.

Once these objects are created, we will use kubectl to obtain the `approvePlan` value
and set it in the `Terraform` object. After making our changes and pushing them to the Git repository,
TF-controller will apply the plan and create the real resources.

## Define the Terraform object

To use the plan & manual approval workflow with TF-controller,
you will need to start by either setting the `spec.approvePlan` field in the `Terraform` object
to be the blank value, or omitting it entirely.
This will tell TF-controller to use the plan & manual approval workflow, rather than the auto-apply workflow.
If you want to use the auto-apply workflow, you will need to set the `spec.approvePlan` field to "auto".

To set the `spec.approvePlan` field to be the blank value,
you can include it in the spec field and set it to an empty string.
Alternatively, you can omit the `spec.approvePlan` field entirely and let it default to the blank value.

In addition to setting the `spec.approvePlan` field, you will also need to specify the `interval`, `path`,
and `sourceRef` fields in the spec field.
The `interval` field determines how often TF-controller will run the Terraform configuration,
the `path` field specifies the location of the configuration files,
and the `sourceRef` field points to the GitRepository object.

```yaml {7}
apiVersion: infra.contrib.fluxcd.io/v1alpha1
kind: Terraform
metadata:
  name: helloworld
  namespace: flux-system
spec:
  approvePlan: "" # or you can omit this field
  interval: 1m
  path: ./
  sourceRef:
    kind: GitRepository
    name: helloworld
    namespace: flux-system
```

## View the approval message

After setting the approvePlan field in the Terraform object and creating any necessary objects, the controller will generate a plan and output a message about how to use the approvePlan field to approve the plan.

To obtain this message, you can run the following command:

```bash
kubectl -n flux-system get tf/helloworld
```

This command will output the message containing the approvePlan value
that you will need to use to approve the plan.
Once you have this value, you can edit the Terraform object file, and set the `spec.approvePlan` field
to the value obtained from the message.

After making your changes and pushing them to the Git repository,
TF-controller will apply the plan and create the real resources.
This process is known as the plan & manual approval workflow,
as it involves generating a plan and requiring manual approval before the changes are applied.

```yaml {7}
apiVersion: infra.contrib.fluxcd.io/v1alpha1
kind: Terraform
metadata:
  name: hello-world
  namespace: flux-system
spec:
  approvePlan: plan-main-b8e362c206 # first 8 digits of a commit hash is enough
  interval: 1m
  path: ./
  sourceRef:
    kind: GitRepository
    name: helloworld
    namespace: flux-system
```
